/*
 * comlan
 */

package com.comlan.installer;

import java.io.File;
import java.util.HashMap;
import java.util.Map;


import android.app.Service;
import android.content.Intent;
import android.content.pm.IPackageInstallObserver;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.Log;
import android.widget.Toast;

public class InstallerService extends Service {
	private static final String INTENT_ACTION_INSTALLCOMPLETED = "com.comlan.mterm.installcompleted";
	private static final String TAG = "installer";
	private final int INSTALL_COMPLETE = 1;
	Uri mPackageURI;// =
					// Uri.parse("file:///data/data/com.comlan.mterm.tms/app/install/vudroid.apk");
	String installerPackageName;// = "org.vudroid";
	private PackageParser.Package mPkgInfo;
	private Map<String, App> map = new HashMap<String, App>();

	public App getAppFromPackName(String packName) {
		App app = map.get(packName);
		return app; 
	}

	private Handler mHandler = new Handler() {
		public void handleMessage(Message msg) {
			Intent intent = new Intent();
			intent.setAction(INTENT_ACTION_INSTALLCOMPLETED);
			String packageName = (String) msg.obj;
			App app = getAppFromPackName(packageName);
			switch (msg.what) {
			case INSTALL_COMPLETE:
				String path = "";
				int id = -1;
				if(app != null){
					if(app.getPath()!=null){
						path = app.getPath();
					}
					id = app.getId();
				}
				Log.d(TAG, "path = " + path);
				Log.d(TAG, "msg.arg1 = " + msg.arg1);
				if (msg.arg1 == PackageManager.INSTALL_SUCCEEDED) {
					if(id == -100){
						Toast.makeText(InstallerService.this, packageName + " 重装成功!", Toast.LENGTH_LONG).show();
					}else{
						intent.putExtra("install", true);
						
						intent.putExtra("path", path);
						intent.putExtra("id", id);
						Log.d(TAG, "-----------------------------\nsend broadcast from installer : install = true \nid =  " + id + "\npath = " + path);
	//					Toast.makeText(InstallerService.this, "install completed : " + packageName, Toast.LENGTH_SHORT).show();
					}
				} else {
					intent.putExtra("install", false);
					intent.putExtra("path", path);
					intent.putExtra("id", id);
					Log.d(TAG, "-----------------------------\nsend broadcast from installer : install = false \nid =  " + id + "\npath = " + path);
//					Toast.makeText(InstallerService.this, "install failed : " + packageName, Toast.LENGTH_SHORT).show();
				}
				sendBroadcast(intent);
				break;
			default:
				break;
			}
		}
	};

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}

	class PackageInstallObserver extends IPackageInstallObserver.Stub {

		public void packageInstalled(String packageName, int returnCode) {
			Message msg = mHandler.obtainMessage(INSTALL_COMPLETE);
			msg.arg1 = returnCode;
			msg.obj = packageName;
			mHandler.sendMessage(msg);
		}
	}

	@Override
	public void onCreate() {
		super.onCreate();

	}
	
	@Override
	public void onStart(Intent intent, int startId) {
		// TODO Auto-generated method stub
		super.onStart(intent, startId);
		PackageManager pm = getPackageManager();
		int installFlags = 0;
		PackageInstallObserver observer = new PackageInstallObserver();
		String path = "";
//		String signature = "";
//		String md5 = "";
		int id = -1 ;
		try {
			// get uri
			id = intent.getIntExtra("id", -1);
			path = intent.getStringExtra("path");
//			signature = intent.getStringExtra("signature");
//			md5 = intent.getStringExtra("md5");
			
			Log.d(TAG, "installer onStart() path = " + path);
			mPackageURI = Uri.parse(path);

			// prepare install info.
			mPkgInfo = getPackageInfo(mPackageURI);
			installerPackageName = mPkgInfo.applicationInfo.packageName;
			Log.d(TAG, "installerPackageName = " + installerPackageName);
			map.put(installerPackageName, new App(id, path));
			try {
				PackageInfo pi = pm.getPackageInfo(installerPackageName, PackageManager.GET_UNINSTALLED_PACKAGES);
				if (pi != null) {
					installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
				}
			} catch (Exception e) {
			}
			pm.installPackage(mPackageURI, observer, installFlags, installerPackageName);
		} catch (Exception e) {
			e.printStackTrace();
			Intent intent1 = new Intent();
			intent1.setAction(INTENT_ACTION_INSTALLCOMPLETED);
			intent1.putExtra("path", path);
			intent1.putExtra("id", id);
			intent1.putExtra("install", false);
			Log.d(TAG, "path: " + path);
			Log.d(TAG, "id: " + id);
			Log.d(TAG, "install: false");
			sendBroadcast(intent1);
		}
//		String publicKeyFile = "sdcard/update/publicKey.txt";
//		String publicKeyFile = "/data/data/com.comlan.mterm.tms/publicKey.txt";
//		boolean val = false;
//		try {
//			val = RSACoder.validateByMD5(signature, publicKeyFile , md5);
//		} catch (Exception e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		if(val){
//			pm.installPackage(mPackageURI, observer, installFlags, installerPackageName);
//			Log.d(TAG, "install service validate = " + val);
//		}else{
//			Intent intent1 = new Intent();
//			intent1.setAction(INTENT_ACTION_INSTALLCOMPLETED);
//			intent1.putExtra("path", path);
//			intent1.putExtra("id", id);
//			intent1.putExtra("install", false);
//			sendBroadcast(intent1);
//		}
			
	} 

	/*
	 * Utility method to get package information for a given packageURI
	 */
	public static PackageParser.Package getPackageInfo(Uri packageURI) {
		final String archiveFilePath = packageURI.getPath();
		PackageParser packageParser = new PackageParser(archiveFilePath);
		File sourceFile = new File(archiveFilePath);
		DisplayMetrics metrics = new DisplayMetrics();
		metrics.setToDefaults();
		PackageParser.Package pkg = packageParser.parsePackage(sourceFile, archiveFilePath, metrics, 0);
		// Nuke the parser reference.
		packageParser = null;
		return pkg;
	}

	class App {
		private int id;
		private String path = "";
//		private String signature;
//		private String md5;
		public App(int id, String path) {
			super();
			this.id = id;
			this.path = path;
		}

//		public App(int id, String path, String signature, String md5) {
//			this.id = id;
//			this.path = path;
//			this.signature = signature;
//			this.md5 = md5;
//		}

		public int getId() {
			return id;
		}

		public void setId(int id) {
			this.id = id;
		}

		public String getPath() {
			if(path == null){
				path = "";
			}
			return path;
		}

		public void setPath(String path) {
			this.path = path;
		}

	}
}
